package com.lambda.hybrid.handler;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.StatFs;
import android.text.TextUtils;

import com.lambda.hybrid.Callback;
import com.lambda.hybrid.utils.Util;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class SaveImageToAlbumHandler extends AbstractHandler implements Handler.Callback {
    private final Context mContext;
    private final Handler handler;
    private final Map<String, Callback> mTaskTable = new HashMap<>();

    public SaveImageToAlbumHandler(Context context) {
        mContext = context;
        handler = new Handler(this);
    }

    @Override
    public void onHandle(String data, Callback callback) throws Exception {
        JSONObject table = new JSONObject(data);

        final String imageURL = table.getString("url");

        if (!mTaskTable.containsKey(imageURL)) {

            ImageDownloader downloader = new ImageDownloader(imageURL);
            new Thread(downloader).start();

            mTaskTable.put(imageURL, callback);
        } else {
            callback.invoke("{\"code\", 2}");
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        FetchImageResp resp = (FetchImageResp) msg.obj;
        switch (msg.what) {
            case 1: // success
                if (mContext != null) {
                    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    intent.setData(Uri.fromFile(resp.file));
                    mContext.sendBroadcast(intent);
                }
                response(resp, true);
                break;

            case -1: // error occurs
                response(resp, false);
                break;
        }
        return true;
    }

    private void response(FetchImageResp resp, boolean success) {
        Callback callback = mTaskTable.remove(resp.url);
        if (callback != null) {
            JSONObject result = new JSONObject();
            try {
                result.put("code", success ? 1 : -1);
                if (!TextUtils.isEmpty(resp.msg)) {
                    result.put("msg", resp.msg);
                }
            } catch (JSONException e) {/**/}
            callback.invoke(result.toString());
        }
    }

    static final class FetchImageResp {
        final String url;
        final File file;
        final String msg;

        FetchImageResp(String url, File file) {
            this.url = url;
            this.file = file;
            this.msg = null;
        }

        FetchImageResp(String url, String msg) {
            this.url = url;
            this.file = null;
            this.msg = msg;
        }
    }

    private final class ImageDownloader implements Runnable {
        private final String imageURL;

        private ImageDownloader(String imageURL) {
            this.imageURL = imageURL;
        }

        @Override
        public void run() {
            HttpURLConnection connection = null;
            FileOutputStream fos = null;
            try {
                File others = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Others");
                if (!others.exists() && !others.mkdirs()) throw new IOException("创建目录失败");

                connection = (HttpURLConnection) new URL(imageURL).openConnection();
                final int code = connection.getResponseCode();
                if (code < 400) {
                    String contentLength = connection.getHeaderField("Content-Length");
                    long length = Long.parseLong(contentLength);
                    StatFs statFs = new StatFs(others.getAbsolutePath());
                    if (statFs.getAvailableBytes() < length) throw new IOException("存储空间不足");

                    String contentType = connection.getHeaderField("Content-Type");
                    String subfix = null;
                    if (!TextUtils.isEmpty(contentType) && contentType.contains("image/")) {
                        subfix = contentType.substring(6);
                    }

                    StringBuilder pattern = new StringBuilder(Util.md5(imageURL));
                    if (!TextUtils.isEmpty(subfix)) {
                        pattern.append(".").append(subfix);
                    }

                    File targetImageFile = new File(others, pattern.toString());
                    if (!targetImageFile.exists()) {
                        if (!targetImageFile.createNewFile()) throw new IOException("创建文件失败");

                        fos = new FileOutputStream(targetImageFile);
                        InputStream inputStream = connection.getInputStream();
                        byte[] buf = new byte[1024];
                        int len;
                        while (-1 != (len = inputStream.read(buf))) {
                            fos.write(buf, 0, len);
                        }
                    }
                    handler.obtainMessage(1, new FetchImageResp(imageURL, targetImageFile)).sendToTarget();
                } else {
                    String msg = connection.getResponseMessage();
                    handler.obtainMessage(-1, new FetchImageResp(imageURL, msg)).sendToTarget();
                }
            } catch (Exception e) {
                handler.obtainMessage(-1, new FetchImageResp(imageURL, e.getLocalizedMessage())).sendToTarget();
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }

                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {/**/}
                }
            }
        }
    }
}
